
#include "testcommon.h"

/* Empty function *************************************************************/

JNIEXPORT void JNICALL Java_com_googlecode_dni_test_Performance_empty( JNIEnv* env, jclass c )
{
}

JNIEXPORT void performance_empty()
{
}


/* int-taking function ********************************************************/

JNIEXPORT jint JNICALL Java_com_googlecode_dni_test_Performance_ints( JNIEnv* env, jclass c, jint x, jint y )
{
	return x + y;
}

JNIEXPORT jint performance_ints( jint x, jint y )
{
	return x + y;
}


/* float-taking function ******************************************************/

JNIEXPORT jfloat JNICALL Java_com_googlecode_dni_test_Performance_floats( JNIEnv* env, jclass c, jfloat x, jfloat y )
{
	return x + y;
}

JNIEXPORT jfloat performance_floats( jfloat x, jfloat y )
{
	return x + y;
}


/* double-taking function *****************************************************/

JNIEXPORT jdouble JNICALL Java_com_googlecode_dni_test_Performance_doubles( JNIEnv* env, jclass c, jdouble x, jdouble y )
{
	return x + y;
}

JNIEXPORT jdouble performance_doubles( jdouble x, jdouble y )
{
	return x + y;
}


/* ByteBuffer-taking function *************************************************/

JNIEXPORT jbyte JNICALL Java_com_googlecode_dni_test_Performance_buffer( JNIEnv* env, jclass c, jobject buffer )
{
	void* ptr;

	ptr = (*env)->GetDirectBufferAddress(env, buffer);
	if ( ptr == 0 )
		return -1;

	return *((jbyte*) ptr);
}

JNIEXPORT jbyte performance_buffer( jbyte* ptr )
{
	return *ptr;
}


/* structure-taking function 1 ************************************************/

struct test1
{
    int x;
    int y;
    double p;
    double q;
};

JNIEXPORT jint JNICALL Java_com_googlecode_dni_test_TestStruct1J_compute( JNIEnv* env, jobject s )
{
	struct test1 v;

    // obviously not thread-safe, but suitable for this little perf test
    static int initialised = 0;
    static jfieldID x = NULL;
    static jfieldID y = NULL;
    static jfieldID p = NULL;
    static jfieldID q = NULL;
    
    if ( initialised == 0 )
    {
        jclass structClass = (*env)->GetObjectClass( env, s );
        x = (*env)->GetFieldID( env, structClass, "x", "I" );
        y = (*env)->GetFieldID( env, structClass, "y", "I" );
        p = (*env)->GetFieldID( env, structClass, "p", "D" );
        q = (*env)->GetFieldID( env, structClass, "q", "D" );
        initialised = 1;
    }
    
    v.x = (*env)->GetIntField( env, s, x );
    v.y = (*env)->GetIntField( env, s, y );
    v.p = (*env)->GetDoubleField( env, s, p );
    v.q = (*env)->GetDoubleField( env, s, q );

    return v.x + v.y + (int) v.p + (int) v.q;
}

JNIEXPORT int performance_teststruct1_compute( struct test1 v )
{
	return v.x + v.y + (int) v.p + (int) v.q;
}


/* structure-taking function 2 ************************************************/

JNIEXPORT void JNICALL Java_com_googlecode_dni_test_TestStruct1J_update( JNIEnv* env, jobject s )
{
	struct test1 v;

    // obviously not thread-safe, but suitable for this little perf test
    static int initialised = 0;
    static jfieldID x = NULL;
    static jfieldID y = NULL;
    static jfieldID p = NULL;
    static jfieldID q = NULL;
    
    if ( initialised == 0 )
    {
        jclass structClass = (*env)->GetObjectClass( env, s );
        x = (*env)->GetFieldID( env, structClass, "x", "I" );
        y = (*env)->GetFieldID( env, structClass, "y", "I" );
        p = (*env)->GetFieldID( env, structClass, "p", "D" );
        q = (*env)->GetFieldID( env, structClass, "q", "D" );
        initialised = 1;
    }
    
    v.x = (*env)->GetIntField( env, s, x );
    v.y = (*env)->GetIntField( env, s, y );
    v.p = (*env)->GetDoubleField( env, s, p );
    v.q = (*env)->GetDoubleField( env, s, q );

    // now swap x & y and p & q
    (*env)->SetIntField( env, s, x, v.y );
    (*env)->SetIntField( env, s, y, v.x );
    (*env)->SetIntField( env, s, p, v.q );
    (*env)->SetIntField( env, s, q, v.p );
}

JNIEXPORT void performance_teststruct1_update( struct test1* v )
{
    struct test1 w = *v;
	v->x = w.y;
	v->y = w.x;
	v->p = w.q;
	v->q = w.p;
}
